package com.skzh.system.service.impl;

import com.skzh.common.annotation.DataScope;
import com.skzh.common.constant.UserConstants;
import com.skzh.common.core.domain.TreeSelect;
import com.skzh.common.core.domain.entity.SysRegion;
import com.skzh.common.core.domain.entity.SysRole;
import com.skzh.common.core.domain.entity.SysUser;
import com.skzh.common.core.text.Convert;
import com.skzh.common.exception.ServiceException;
import com.skzh.common.utils.SecurityUtils;
import com.skzh.common.utils.StringUtils;
import com.skzh.common.utils.spring.SpringUtils;
import com.skzh.system.mapper.SysRegionMapper;
import com.skzh.system.mapper.SysRoleMapper;
import com.skzh.system.service.ISysRegionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 区域管理 服务实现
 *
 * @author skzh
 */
@Service
public class SysRegionServiceImpl implements ISysRegionService {
    @Autowired
    private SysRegionMapper regionMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    /**
     * 查询区域管理数据
     *
     * @param region 区域信息
     * @return 区域信息集合
     */
    @Override
    public List<SysRegion> selectRegionList(SysRegion region) {
        return regionMapper.selectRegionList(region);
    }

    /**
     * 查询区域树结构信息
     *
     * @param region 区域信息
     * @return 区域树信息集合
     */
    @Override
    public List<TreeSelect> selectRegionTreeList(SysRegion region) {
        List<SysRegion> regions = SpringUtils.getAopProxy(this).selectRegionList(region);
        return buildRegionTreeSelect(regions);
    }

    /**
     * 构建前端所需要树结构
     *
     * @param regions 区域列表
     * @return 树结构列表
     */
    @Override
    public List<SysRegion> buildRegionTree(List<SysRegion> regions) {
        List<SysRegion> returnList = new ArrayList<SysRegion>();
        List<Long> tempList = regions.stream().map(SysRegion::getRegionId).collect(Collectors.toList());
        for (SysRegion region : regions) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(region.getParentId())) {
                recursionFn(regions, region);
                returnList.add(region);
            }
        }
        if (returnList.isEmpty()) {
            returnList = regions;
        }
        return returnList;
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param regions 区域列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> buildRegionTreeSelect(List<SysRegion> regions) {
        List<SysRegion> regionTrees = buildRegionTree(regions);
        return regionTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 根据角色ID查询区域树信息
     *
     * @param roleId 角色ID
     * @return 选中区域列表
     */
    @Override
    public List<Long> selectRegionListByRoleId(Long roleId) {
        SysRole role = roleMapper.selectRoleById(roleId);
        return regionMapper.selectRegionListByRoleId(roleId, role.isDeptCheckStrictly());
    }

    /**
     * 根据区域ID查询信息
     *
     * @param regionId 区域ID
     * @return 区域信息
     */
    @Override
    public SysRegion selectRegionById(Long regionId) {
        return regionMapper.selectRegionById(regionId);
    }

    /**
     * 根据ID查询所有子区域（正常状态）
     *
     * @param regionId 区域ID
     * @return 子区域数
     */
    @Override
    public int selectNormalChildrenRegionById(Long regionId) {
        return regionMapper.selectNormalChildrenRegionById(regionId);
    }

    /**
     * 是否存在子节点
     *
     * @param regionId 区域ID
     * @return 结果
     */
    @Override
    public boolean hasChildByRegionId(Long regionId) {
        int result = regionMapper.hasChildByRegionId(regionId);
        return result > 0;
    }

    /**
     * 查询区域是否存在用户
     *
     * @param regionId 区域ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkRegionExistUser(Long regionId) {
        int result = regionMapper.checkRegionExistUser(regionId);
        return result > 0;
    }

    /**
     * 校验区域名称是否唯一
     *
     * @param region 区域信息
     * @return 结果
     */
    @Override
    public boolean checkRegionNameUnique(SysRegion region) {
        Long regionId = StringUtils.isNull(region.getRegionId()) ? -1L : region.getRegionId();
        SysRegion info = regionMapper.checkRegionNameUnique(region.getRegionName(), region.getParentId());
        if (StringUtils.isNotNull(info) && info.getRegionId().longValue() != regionId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验区域是否有数据权限
     *
     * @param regionId 区域id
     */
    @Override
    public void checkRegionDataScope(Long regionId) {
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            SysRegion region = new SysRegion();
            region.setRegionId(regionId);
            List<SysRegion> regions = SpringUtils.getAopProxy(this).selectRegionList(region);
            if (StringUtils.isEmpty(regions)) {
                throw new ServiceException("没有权限访问区域数据！" );
            }
        }
    }

    /**
     * 新增保存区域信息
     *
     * @param region 区域信息
     * @return 结果
     */
    @Override
    public int insertRegion(SysRegion region) {
        SysRegion info = regionMapper.selectRegionById(region.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!UserConstants.REGION_NORMAL.equals(info.getStatus())) {
            throw new ServiceException("区域停用，不允许新增" );
        }
        region.setAncestors(info.getAncestors() + "," + region.getParentId());
        return regionMapper.insertRegion(region);
    }

    /**
     * 修改保存区域信息
     *
     * @param region 区域信息
     * @return 结果
     */
    @Override
    public int updateRegion(SysRegion region) {
        SysRegion newParentRegion = regionMapper.selectRegionById(region.getParentId());
        SysRegion oldRegion = regionMapper.selectRegionById(region.getRegionId());
        if (StringUtils.isNotNull(newParentRegion) && StringUtils.isNotNull(oldRegion)) {
            String newAncestors = newParentRegion.getAncestors() + "," + newParentRegion.getRegionId();
            String oldAncestors = oldRegion.getAncestors();
            region.setAncestors(newAncestors);
            updateRegionChildren(region.getRegionId(), newAncestors, oldAncestors);
        }
        int result = regionMapper.updateRegion(region);
        if (UserConstants.REGION_NORMAL.equals(region.getStatus()) && StringUtils.isNotEmpty(region.getAncestors())
                && !StringUtils.equals("0" , region.getAncestors())) {
            // 如果该区域是启用状态，则启用该区域的所有上级区域
            updateParentRegionStatusNormal(region);
        }
        return result;
    }

    /**
     * 修改该区域的父级区域状态
     *
     * @param region 当前区域
     */
    private void updateParentRegionStatusNormal(SysRegion region) {
        String ancestors = region.getAncestors();
        Long[] regionIds = Convert.toLongArray(ancestors);
        regionMapper.updateRegionStatusNormal(regionIds);
    }

    /**
     * 修改子元素关系
     *
     * @param regionId       被修改的区域ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateRegionChildren(Long regionId, String newAncestors, String oldAncestors) {
        List<SysRegion> children = regionMapper.selectChildrenRegionById(regionId);
        for (SysRegion child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            regionMapper.updateRegionChildren(children);
        }
    }

    /**
     * 删除区域管理信息
     *
     * @param regionId 区域ID
     * @return 结果
     */
    @Override
    public int deleteRegionById(Long regionId) {
        return regionMapper.deleteRegionById(regionId);
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysRegion> list, SysRegion t) {
        // 得到子节点列表
        List<SysRegion> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysRegion tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysRegion> getChildList(List<SysRegion> list, SysRegion t) {
        List<SysRegion> tlist = new ArrayList<SysRegion>();
        Iterator<SysRegion> it = list.iterator();
        while (it.hasNext()) {
            SysRegion n = (SysRegion) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getRegionId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysRegion> list, SysRegion t) {
        return getChildList(list, t).size() > 0;
    }
}
